package demo.isolib.movement {
	import as3isolib.geom.Pt;
	
	import demo.gemo.GridPoint;
	import demo.isolib.Directions;
	import demo.isolib.Tile;
	import demo.isolib.TileEvent;
	import com.sshc625.log.Logger;
	import demo.isolib.movement.TileMovement;

	/**
	 */
	public class TileMovement extends DummyTileMovement implements ITileMovement {
		protected var _tile:Tile;
		protected var _speed:uint;

		/**
		 * @parameter spd 	The speed of movable object, 10 pixel pre second by default.
		 */
		public function TileMovement(spd:uint = 100) {
			Logger.log("new TileMovement");
			this.speed = spd;
		}

		override public function execute(params:Array = null):void {
			Logger.log("TileMovement.execute(" + params + ")");
			
			if (params) {
				if (params[0] + tile.colSpan > tile.world.grid.gridSize[0] ) {
					params[0] = tile.world.grid.gridSize[0]  - tile.colSpan;
				}
				if (params[1] + tile.rowSpan > tile.world.grid.gridSize[1] ) {
					params[1] = tile.world.grid.gridSize[1]  - tile.rowSpan;
				}
				
				// 
				var x:Number = params[0];
				var y:Number = params[1];
				var screenPt:Pt = tile.world.gridToIso( x,y );
				tile.faceDirection = getFaceDirection(screenPt.x, screenPt.y);			
			}
		}

		override public function abort():void {
			Logger.log("TileMovement.abort()");
			this._tile.dispatchEvent(new TileEvent(TileEvent.MOVE_ABORT));
		}

		public function get speed():uint {
			return this._speed;
		}

		public function set speed(spd:uint):void {
			this._speed = spd;
		}

		/**
		 *
		 */
		protected function start(... args):void {
			Logger.log("TileMovement.start(" + args + ")  tile.name="+this.tile.name);			
			this.tile.dispatchEvent(new TileEvent(TileEvent.MOVE_START));
		}

		/**
		 *
		 */
		protected function update(... args):void {
			this.tile.dispatchEvent(new TileEvent(TileEvent.MOVE_UPDATE));
		}

		/**
		 *
		 */
		protected function complete(... args):void {
			Logger.log("TileMovement.complete(" + args + ")");
			this.tile.dispatchEvent(new TileEvent(TileEvent.MOVE_COMPLETE));
		}

		/**
		 * The direction the tile should face
		 */
		protected function getFaceDirection(x:Number, y:Number):String {

			if (x > tile.x && y > tile.y) {
				return Directions.S;
			} else if (x > tile.x && y < tile.y) {
				return Directions.E;
			} else if (x > tile.x && y == tile.y) {
				return Directions.SE;
			} else if (x == tile.x && y > tile.y) {
				return Directions.SW;
			} else if (x == tile.x && y < tile.y) {
				return Directions.NE;
			} else if (x < tile.x && y > tile.y) {
				return Directions.W;
			} else if (x < tile.x && y < tile.y) {
				return Directions.N;
			} else if (x < tile.x && y == tile.y) {
				return Directions.NW;
			} else {
				return tile.faceDirection;
			}

			return null;
		}

		/**
		 * Update walkable properties of the world's astargrid
		 * @param	walkable
		 */
		protected function updateAstarGrid(walkable:Boolean):void {
			if (tile == null) {
				return;
			}
			for (var i:int = 0; i < tile.colSpan; i++) {
				for (var j:int = 0; j < tile.rowSpan; j++) {
					tile.world.astarGrid.setWalkable(tile.column + i, tile.row + j, walkable);
				}
			}
		}

		override public function get tile():Tile {
			return _tile;
		}

		override public function set tile(value:Tile):void {
			_tile = value;
		}

	}

}